package engine.BIEngine0_1;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;

import beans.AlgorithmDetail;
import beans.AlgorithmOutput;
import beans.HttpConfig;
import beans.RunningTaskBean;
import beans.UIAlgorithmDetail;
import beans.UIBlock;
import beans.UIInputConfig;
import beans.UILine;
import beans.UIParamConfig;
import dao.AlgorithmDao;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.JSONArray;
//import com.alibaba.fastjson.parser.
//import net.sf.json.JSONArray;
//import net.sf.json.JSONObject;
import utils.Log4jInit;
import utils.Time2Str;

public class ParseTaskJson {
	private AlgorithmDao algorithmDao;
	// private String staticOutputUri = HttpConfig.tempOutput;
	private String staticOutputUri = HttpConfig.wfTempOutput;
	private ArrayList<UIAlgorithmDetail> orderedDetails;
	private Map<String, UIBlock> blockParseResult;
	private JSONObject taskJson;
	private JSONObject otherConfig;
	// algorithm details:<key:algorithmId, value:algorithmDetail>
	private Map<String, AlgorithmDetail> algorithmDetails;
	private SimpleDateFormat sf = new SimpleDateFormat("yyyy_MM_dd_HH_mm_ss");
	SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");

	public ParseTaskJson() {
		super();
		this.algorithmDao = new AlgorithmDao();
		orderedDetails = new ArrayList<>();
		blockParseResult = new HashMap<>();
		algorithmDetails = new HashMap<>();
	}

	/**
	 * parse the pre and post relationship between blocks
	 * 
	 * @param json
	 * @return map(key : block id ; value : UIBlock)
	 */
	// @SuppressWarnings("Duplicates")
	// private Map<String, UIBlock> parseTaskJson(String json) {
	// if(this.blockParseResult.size()==0){
	// JSONObject jsonObject = JSONObject.fromObject(json);
	// return parseTaskJson(jsonObject);
	// }
	//
	// return this.blockParseResult;
	// }

	private Map<String, UIBlock> parseTaskJson(JSONObject jsonObject) {
		if (this.blockParseResult.size() == 0) {
			// JSONObject jsonObject = JSONObject.fromObject(json);
			List<String> firstBlock = new ArrayList<>();
			JSONArray blocksArray = jsonObject.getJSONArray("blocks");
			/**
			 * record a block is algorithm or model key:block id value: 1:is
			 * algorithm 0:is model
			 */
			Map<String, Integer> algorithmOrModel = new HashMap<>();
			for (int a = 0; a < blocksArray.size(); a++) {
				JSONObject block = blocksArray.getJSONObject(a);
				String blockId = block.getString("blockId");
				if (!(blockId.contains("uiStart") || blockId.contains("uiEnd") || blockId.contains("uiData"))) {
					algorithmOrModel.put(blockId, block.getString("isAlgorithm").equals("1") ? 1 : 0);
				} else {
					algorithmOrModel.put(blockId, 2);
				}
			}

			/**
			 * produce block map key:blockId value:block json
			 */
			Map<String, JSONObject> blocksMap = new HashMap<>();
			for (int i = 0; i < blocksArray.size(); i++) {
				JSONObject blockObject = JSONObject.parseObject(blocksArray.get(i).toString());// JSONObject.fromObject(blocksArray.get(i));
				blocksMap.put(blockObject.getString("blockId"), blockObject);
			}

			/**
			 * produce line list
			 */
			// JSONArray lines = jsonObject.getJSONArray("lines");
			Collection<?> uiLines = JSONArray.parseArray(jsonObject.getString("lines"), UILine.class);// JSONArray.toCollection(lines,
																										// UILine.class);
			ArrayList<UILine> lineList = new ArrayList<>();
			for (Object o : uiLines) {
				lineList.add((UILine) o);
			}

			/**
			 * parse each block, produce each one's postMap
			 */
			Map<String, UIBlock> blocks = new HashMap<>();
			blocks.put("uiEnd", new UIBlock());
			for (UILine line : lineList) {
				if (!line.getPageTargetId().contains("uiEnd")) {
					orderedDetails.add(new UIAlgorithmDetail(line.getPageTargetId()));
				} else {
					blocks.get("uiEnd").preBlockMap.put(line.getPageSourceId(),
							algorithmOrModel.get(line.getPageSourceId()));
				}
				if (line.getPageSourceId().equals("uiStart_1")) {
					firstBlock.add(line.getPageTargetId());
				}
				if (!blocks.containsKey(line.getPageSourceId())) {
					UIBlock sourceBlock = new UIBlock();
					sourceBlock.setBlockId(line.getPageSourceId());
					sourceBlock.postBlockMap.put(line.getPageTargetId(), algorithmOrModel.get(line.getPageTargetId()));
					blocks.put(line.getPageSourceId(), sourceBlock);
				} else {
					blocks.get(line.getPageSourceId()).postBlockMap.put(line.getPageTargetId(),
							algorithmOrModel.get(line.getPageTargetId()));
				}
			}

			for (Map.Entry<String, JSONObject> block : blocksMap.entrySet()) {
				if (!(block.getKey().contains("uiStart") || block.getKey().contains("uiEnd")
						|| block.getKey().contains("uiData"))) {
					/**
					 * parse current block into UIBlock bean
					 */
					UIBlock tempBlock = blocks.get(block.getKey());
					tempBlock.setId(block.getValue().getString("dataId"));
					tempBlock.setAlgorithm(block.getValue().getString("isAlgorithm").equals("1"));
					if (tempBlock.isAlgorithm()) {
						AlgorithmDetail algorithmDetail = algorithmDao
								.getAlgorithmDetailWithoutUserId(tempBlock.getId());
						if (block.getValue().containsKey("cpuNum")) {
							algorithmDetail.setCpuNum(block.getValue().getString("cpuNum"));
						}
						algorithmDetails.put(tempBlock.getId(), algorithmDetail);
						tempBlock.setAlgorithmOrModel(algorithmDetails.get(tempBlock.getId()));
					}
					/**
					 * produce UIInputConfig list
					 */

					if (block.getValue().containsKey("inputConfig")) {

						tempBlock.inputConfig = parseInputs(block.getValue().getJSONArray("inputConfig"), tempBlock,
								algorithmOrModel);
					}

				}
			}

			/**
			 * print results
			 */
			// for (Map.Entry<String, UIBlock> blockssss : blocks.entrySet()) {
			// Log4jInit.logger.info(">>>>>\n\t\t\t" + blockssss.getKey() + ":"
			// + blockssss.getValue().toString());
			// }
			this.blockParseResult = blocks;
		}

		return this.blockParseResult;
	}

	private List<UIParamConfig> parseParams(JSONArray paramsArray) {
		List<UIParamConfig> uiParams = new ArrayList<>();
		for (int in = 0; in < paramsArray.size(); in++) {
			JSONObject oneParam = paramsArray.getJSONObject(in);
			UIParamConfig param = new UIParamConfig();
			param.setParamName(oneParam.getString("paramName"));
			param.setParamValue(oneParam.getString("paramValue"));
			uiParams.add(param);
		}
		return uiParams;
	}

	private List<UIInputConfig> parseInputs(JSONArray blockInputsArray, UIBlock tempBlock,
			Map<String, Integer> algorithmOrModel) {
		List<UIInputConfig> uiInputs = new ArrayList<>();
		for (int in = 0; in < blockInputsArray.size(); in++) {
			JSONObject oneInput = blockInputsArray.getJSONObject(in);
			JSONObject frontInfo = oneInput.getJSONObject("frontOutput");
			UIInputConfig oneUIInput = new UIInputConfig();
			oneUIInput.setInputName(oneInput.getString("inputName"));
			oneUIInput.setFrontBlockId(frontInfo.getString("blockId"));
			oneUIInput.setFrontAlgorithmId(frontInfo.getString("dataId"));
			oneUIInput.setFrontOutputName(frontInfo.getString("frontOutputName"));
			tempBlock.preBlockMap.put(frontInfo.getString("blockId"),
					(algorithmOrModel == null) ? 0 : algorithmOrModel.get(frontInfo.getString("blockId")));
			uiInputs.add(oneUIInput);
		}
		return uiInputs;
	}

	/**
	 * produce output map by task json outputs: {"suffix":"","outputs":[]} key:
	 * <blockId>_<output name> value: outputValue
	 * 
	 * @param outputs
	 */
	private HashMap<String, String> produceOutputMap(String taskName, int taskIndex, JSONObject outputs,
			Map<String, UIBlock> blockParseResult) {
		HashMap<String, String> outputsMap = new HashMap<>();
		for (int index = 0; index < outputs.getJSONArray("outputs").size(); index++) {
			JSONObject oneOutput = outputs.getJSONArray("outputs").getJSONObject(index);
			//
			if (oneOutput.getString("outputValue").indexOf(".") > 0
					|| (!oneOutput.getString("outputValue").contains("."))) {
				outputsMap.put(oneOutput.getString("blockId") + "_" + oneOutput.getString("outputName"),
						oneOutput.getString("outputAddress") + oneOutput.getString("outputValue"));
			} else {
				// 默认输出
				// String outputValue = "output_" +
				// oneOutput.getString("blockId") + "_" + (index + 1) + "_" +
				// taskIndex + oneOutput.getString("outputValue");
				// String outputValue = oneOutput.getString("outputAddress")+
				// taskName +"-"+ sf.format(new Date()) + "_task" + taskIndex+
				// "_output" + (index + 1)+ oneOutput.getString("outputValue");
				String outputValue = oneOutput.getString("outputAddress") + taskName + "_task" + taskIndex + "_output"
						+ (index + 1) + oneOutput.getString("outputValue");
				outputsMap.put(oneOutput.getString("blockId") + "_" + oneOutput.getString("outputName"), outputValue);
			}
			// Log4jInit.logger.info(""+oneOutput.getString("blockId")+"_"+oneOutput.getString("outputName")+":"+
			// oneOutput.getString("outputName"));
		}
		return outputsMap;
	}
	// private HashMap<String, String> produceOutputMap(int taskIndex,JSONObject
	// outputs, Map<String, UIBlock> blockParseResult) {
	// HashMap<String, String> outputsMap = new HashMap<>();
	// if(!outputs.getString("suffix").equals("")){
	// for(Map.Entry<String, Integer> endObjects :
	// blockParseResult.get("uiEnd").preBlockMap.entrySet()){
	// UIBlock endUIBlock = blockParseResult.get(endObjects.getKey());
	// if(endUIBlock.isAlgorithm()){
	// AlgorithmDetail algorithmDetail = (AlgorithmDetail)
	// endUIBlock.getAlgorithmOrModel();
	// for(int
	// index=0;index<algorithmDetail.getAlgorithmOutputs().size();index++){
	// String outputValue = "output_" + endUIBlock.getBlockId() + "_" + (index +
	// 1) + "_" + taskIndex + outputs.getString("suffix");
	// outputsMap.put(endUIBlock.getBlockId()+"_"+algorithmDetail.getAlgorithmOutputs().get(index).getOutputName(),
	// outputValue);
	// }
	// }
	// }
	// return outputsMap;
	// }else{
	// for(int index=0;index<outputs.getJSONArray("outputs").size();index++){
	// JSONObject oneOutput =
	// outputs.getJSONArray("outputs").getJSONObject(index);
	// outputsMap.put(oneOutput.getString("blockId")+"_"+oneOutput.getString("outputName"),
	// oneOutput.getString("outputValue"));
	//// Log4jInit.logger.info(""+oneOutput.getString("blockId")+"_"+oneOutput.getString("outputName")+":"+
	//// oneOutput.getString("outputName"));
	// }
	// return outputsMap;
	// }
	// }

	@SuppressWarnings("unused")
	private Result parseModelJson(String json) {

		JSONObject jsonObject = JSONObject.parseObject(json);
		String firstBlock = "";
		JSONArray blocksArray = jsonObject.getJSONArray("blocks");
		/**
		 * record a block is algorithm or model key:block id value: 1:is
		 * algorithm 0:is model
		 */
		Map<String, Integer> algorithmOrModel = new HashMap<>();
		for (int a = 0; a < blocksArray.size(); a++) {
			JSONObject block = blocksArray.getJSONObject(a);
			String blockId = block.getString("blockId");
			if (blockId.equals("uistart_1") || blockId.equals("uiend_1")) {
				continue;
			} else {
				algorithmOrModel.put(blockId, block.getBoolean("isAlgorithm") ? 1 : 0);
			}
		}
		/**
		 * parse blocks
		 */
		// blocksMap key:block id; value:json
		Map<String, JSONObject> blocksMap = new HashMap<>();
		for (int i = 0; i < blocksArray.size(); i++) {
			JSONObject blockObject = JSONObject.parseObject(blocksArray.get(i).toString());
			blocksMap.put(blockObject.getString("blockId"), blockObject);
		}
		/**
		 * parse lines
		 */
		// JSONArray lines = jsonObject.getJSONArray("lines");
		Collection<?> uiLines = JSONArray.parseArray(jsonObject.getString("lines"), UILine.class);
		ArrayList<UILine> lineList = new ArrayList<>();
		for (Object o : uiLines) {
			lineList.add((UILine) o);
		}
		Map<String, UIBlock> blocks = new HashMap<>();
		for (UILine line : lineList) {
			/**
			 * parse first block
			 */
			if (line.getPageSourceId().equals("uistart_1")) {
				firstBlock = line.getPageTargetId();
			}
			if (!blocks.containsKey(line.getPageSourceId())) {
				UIBlock uiBlock = new UIBlock();
				uiBlock.setBlockId(line.getPageSourceId());
				uiBlock.postBlockMap.put(line.getPageTargetId(), algorithmOrModel.get(line.getPageTargetId()));
				blocks.put(line.getPageSourceId(), uiBlock);
			} else {
				UIBlock uiBlock = blocks.get(line.getPageSourceId());
				uiBlock.postBlockMap.put(line.getPageTargetId(), algorithmOrModel.get(line.getPageTargetId()));
				blocks.put(line.getPageSourceId(), uiBlock);
			}
		}
		for (Map.Entry<String, JSONObject> block : blocksMap.entrySet()) {
			if (block.getKey().equals("uistart_1") || block.getKey().equals("uiend_1")) {
				continue;
			} else {
				UIBlock tempBlock = blocks.get(block.getKey());
				tempBlock.setId(block.getValue().getString("id"));
				tempBlock.setAlgorithm(block.getValue().getBoolean("isAlgorithm"));
				algorithmOrModel.put(tempBlock.getBlockId(), block.getValue().getBoolean("isAlgorithm") ? 1 : 0);
				if (!block.getKey().equals(firstBlock)) {
					/**
					 * first block has no inputs config inputs
					 */
					JSONArray inputsArray = block.getValue().getJSONArray("inputConfig");
					List<UIInputConfig> uiInputs = new ArrayList<>();
					for (int in = 0; in < inputsArray.size(); in++) {
						JSONObject oneInput = inputsArray.getJSONObject(in);
						JSONObject frontInfor = oneInput.getJSONObject("frontOutput");
						UIInputConfig oneUIInput = new UIInputConfig();
						oneUIInput.setInputName((String) oneInput.getString("inputName"));
						oneUIInput.setFrontBlockId(frontInfor.getString("blockId"));
						tempBlock.preBlockMap.put(frontInfor.getString("blockId"),
								algorithmOrModel.get(frontInfor.getString("blockId")));
						oneUIInput.setFrontOutputName(frontInfor.getString("frontOutputName"));
						uiInputs.add(oneUIInput);
					}
					// tempBlock.inputConfig = uiInputs;
				}

				/**
				 * config params
				 */
				JSONArray paramsArray = block.getValue().getJSONArray("paramsConfig");
				List<UIParamConfig> uiParams = new ArrayList<>();
				for (int in = 0; in < paramsArray.size(); in++) {
					JSONObject oneParam = paramsArray.getJSONObject(in);
					UIParamConfig param = new UIParamConfig();
					param.setParamName(oneParam.getString("paramName"));
					param.setParamValue(oneParam.getString("paramValue"));
					uiParams.add(param);
				}
				// tempBlock.paramConfig = uiParams;

				blocks.put(block.getKey(), tempBlock);
			}
		}
		for (Map.Entry<String, UIBlock> bb : blocks.entrySet()) {
			UIBlock tempBlock = bb.getValue();
			for (Map.Entry<String, Integer> g : tempBlock.postBlockMap.entrySet()) {

			}
		}
		/**
		 * print results
		 */
		// Log4jInit.logger.info(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
		// for (Map.Entry<String, UIBlock> blockssss : blocks.entrySet()) {
		// Log4jInit.logger.info(">>>>>" + blockssss.getKey() + ":" +
		// blockssss.getValue().toString());
		// }
		return null;

	}

	/**
	 * produce input map key:<blockId>_<inputName> value: real data
	 * 
	 * @param results
	 */
	private HashMap<String, String> produceInputMap(Map<String, UIBlock> results, TaskThread taskThread,
			JSONArray dataArray) {
		/**
		 * parse out data to outDataMap
		 */
		HashMap<String, String> inputsMap = new HashMap<>();
		Map<String, String> outDataValue = new HashMap<>();
		for (int index = 0; index < dataArray.size(); index++) {
			JSONObject oneData = dataArray.getJSONObject(index);
			outDataValue.put(oneData.getString("dataName"), oneData.getString("dataValue"));
		}

		/**
		 * parse each block
		 */

		for (Map.Entry<String, UIBlock> oneBlock : results.entrySet()) {
			for (UIInputConfig input : oneBlock.getValue().inputConfig) {
				/**
				 * the blocks which connect start block, the input values of
				 * these can get from frontOutputName
				 */
				if (input.getFrontBlockId().contains("uiStart")) {
					inputsMap.put(oneBlock.getValue().getBlockId() + "_" + input.getInputName(),
							input.getFrontOutputName());
				}
				/**
				 * the blocks which connect out data block the input values of
				 * these can get from data json by frontOutputName
				 */

				else if (input.getFrontBlockId().contains("uiData")) {
					if (HttpConfig.useCacheDisk) {
						inputsMap.put(oneBlock.getValue().getBlockId() + "_" + input.getInputName(), HttpConfig.hdfsDisk
								+ "\\" + outDataValue.get(input.getFrontOutputName()).replaceAll("/", "\\\\"));
					} else {
						inputsMap.put(oneBlock.getValue().getBlockId() + "_" + input.getInputName(),
								algorithmDetails.get(oneBlock.getValue().getId()).getPlatform().equals("linux")
										? HttpConfig.linuxDriverLetter
												+ outDataValue.get(input.getFrontOutputName()).replaceAll("\\\\", "/")
										: HttpConfig.windowsDriverLetter
												+ outDataValue.get(input.getFrontOutputName()).replaceAll("/", "\\\\"));
					}

				}
				/**
				 * other the input values of these : <HttpConfig.tempOutput> +
				 * <taskId> + "/" + <algorithmId> + "/" + <outputName> + "/"
				 */

				else {
					String suffix = getOutputSuffix(input.getFrontAlgorithmId(), input.getFrontOutputName());
					/*
					 * Log4jInit.logger.info("produceInputMap================="+
					 * generateTempOutputUri(taskThread.runningTaskBean.
					 * getTaskHash(), input.getFrontBlockId() ,
					 * input.getInputName(),suffix));
					 * inputsMap.put(oneBlock.getValue().getBlockId() + "_" +
					 * input.getInputName() ,
					 * generateTempOutputUri(taskThread.runningTaskBean.
					 * getTaskHash(), input.getFrontBlockId() ,
					 * input.getFrontOutputName(),suffix));
					 */
					Log4jInit.logger.info("produceInputMap================="
							+ generateTempOutputUri(taskThread.runningTaskBean.getTaskHash(), input.getFrontBlockId(),
									input.getInputName(), suffix));
					inputsMap.put(oneBlock.getValue().getBlockId() + "_" + input.getInputName(),
							generateTempOutputUri(taskThread.runningTaskBean.getTaskHash(), input.getFrontBlockId(),
									input.getFrontOutputName(), suffix));
				}
			}
		}
		return inputsMap;
	}

	/**
	 * produce the temp output file uri of the algorithm in middle of
	 * task(except the algorithms which connected with start block and end
	 * block) here is : <HttpConfig.tempOutput> + <taskHash> + "/" +
	 * <algorithmId> + "/" + <outputName> + "/"
	 * 
	 * @return
	 */
	private String generateTempOutputUri(String taskHash, String algorithmHash, String outputName,
			String outputSuffix) {

		// String tempStr = staticOutputUri + taskHash + "/" + algorithmHash +
		// "/" + outputName + "/";
		String tempStr = staticOutputUri + "/";
		/*
		 * if(FileSystem.get(URI.create("/"+tempStr), new
		 * Configuration())==null){ //HDFS中不存在新建文件夹 FileSystem fs =
		 * FileSystem.get(new URI("/"+tempStr),new Configuration()); Path dfs =
		 * new Path("/"+tempStr); fs.mkdirs(dfs); }
		 */

		if (outputSuffix.equals("")) {

			// return HttpConfig.useTempOutput ?
			// HttpConfig.windowsDriverLetter+tempStr:staticOutputUri;
			return HttpConfig.useTempOutput ? HttpConfig.windowsDriverLetter + tempStr + taskHash + "_" + algorithmHash
					: staticOutputUri;
		} else {
			// return HttpConfig.useTempOutput ?
			// HttpConfig.windowsDriverLetter+tempStr + outputName +
			// outputSuffix:staticOutputUri+ outputName + outputSuffix;
			return HttpConfig.useTempOutput ? HttpConfig.windowsDriverLetter + tempStr + taskHash + "_" + algorithmHash
					+ "_" + outputName + outputSuffix : staticOutputUri + outputName + outputSuffix;
		}

	}

	private HashMap<String, String> parseBlockInputs(HashMap<String, String> inputsMap, UIBlock uiBlock,
			String platform) {

		HashMap<String, String> inputsValue = new HashMap<>();
		for (UIInputConfig input : uiBlock.inputConfig) {
			String inputValue = inputsMap.get(uiBlock.getBlockId() + "_" + input.getInputName());
			if (uiBlock.preBlockMap.containsKey("uiStart_1")) {

				if (HttpConfig.useCacheDisk) {
					inputValue = HttpConfig.hdfsDisk + "\\" + inputValue.replaceAll("/", "\\\\");
				} else {
					if (platform.equals("windows")) {
						inputValue = HttpConfig.windowsDriverLetter + inputValue.replaceAll("/", "\\\\");
					} else {
						// inputValue = HttpConfig.linuxDriverLetter +
						// inputValue.replaceAll("\\\\", "/");
						inputValue = HttpConfig.linuxDriverLetter + inputValue;
					}
				}
			}
			// Log4jInit.logger.info(inputValue+":"+platform);
			inputsValue.put(input.getInputName(), inputValue);
		}
		return inputsValue;
	}

	/**
	 * 在所有位置区别linux和Windows加上盘符 produce outputs for each runnable algorithm
	 * 
	 * @param runnableAlgorithm
	 *            : should contain : blockId; algorithmDetail
	 * @return
	 */
	// private HashMap<String,String> generateAlgorithmOutputs(HashMap<String,
	// String> outputsMap,String platform,
	// beans.RunnableAlgorithm runnableAlgorithm,String taskHash){
	// HashMap<String,String> outputsValue = new HashMap<>();
	// for(AlgorithmOutput
	// output:runnableAlgorithm.getAlgorithmDetail().getAlgorithmOutputs()){
	// String outputMapKey =
	// runnableAlgorithm.getBlockId()+"_"+output.getOutputName();
	// String outputValue = "";
	// if(outputsMap.containsKey(outputMapKey)){
	// outputValue = outputsMap.get(outputMapKey);
	// }else{
	// outputValue = generateTempOutputUri(taskHash,
	// runnableAlgorithm.getBlockId(), output.getOutputName());
	// }
	// if(platform.equals("windows")){
	// outputValue = HttpConfig.windowsDriverLetter +
	// outputValue.replaceAll("/", "\\\\");
	// }else{
	// outputValue = HttpConfig.linuxDriverLetter +
	// outputValue.replaceAll("\\\\", "/");
	// }
	// outputsValue.put(output.getOutputName(), outputValue);
	// }
	// return outputsValue;
	// }

	/**
	 * 仅在最后输出区别linux和windows加上盘符 produce outputs for each runnable algorithm
	 * 
	 * @param runnableAlgorithm
	 *            : should contain : blockId; algorithmDetail
	 * @return
	 */
	private HashMap<String, String> generateAlgorithmOutputs(HashMap<String, String> outputsMap, String platform,
			beans.RunnableAlgorithm runnableAlgorithm, String taskHash, int taskIndex) {
		HashMap<String, String> outputsValue = new HashMap<>();
		int algorIndex = 0;
		for (AlgorithmOutput output : runnableAlgorithm.getAlgorithmDetail().getAlgorithmOutputs()) {
			String outputMapKey = runnableAlgorithm.getBlockId() + "_" + output.getOutputName();
			String outputValue = "";
			algorIndex++;
			if (outputsMap.containsKey(outputMapKey)) {
				outputValue = outputsMap.get(outputMapKey);

				if (HttpConfig.useCacheDisk) {
					outputValue = HttpConfig.cacheDisk + "\\" + outputValue.replaceAll("/", "\\\\");
				} else {
					if (platform.equals("windows")) {
						outputValue = HttpConfig.windowsDriverLetter + outputValue.replaceAll("/", "\\\\");
					} else {
						outputValue = HttpConfig.linuxDriverLetter + outputValue.replaceAll("\\\\", "/");
					}
				}

			} else {
				// outputValue = generateTempOutputUri(taskHash,
				// runnableAlgorithm.getBlockId(),
				// output.getOutputName(),output.getSuffix());
				String taskIndStr = "";
				String AlgorOutIndStr = "";
				
				taskIndStr = spellOutputStr(taskHash,taskIndex,4);
				AlgorOutIndStr = spellOutputStr("OUTPUT",algorIndex,2);

				outputValue = generateTempOutputUri(taskIndStr, runnableAlgorithm.getBlockId(), AlgorOutIndStr,
						output.getSuffix());

				Log4jInit.logger.info("Temp OUT:" + outputValue);
			}

			outputsValue.put(output.getOutputName(), outputValue);
		}
		return outputsValue;
	}
	
	private static String spellOutputStr(String str,int index,int num){
		
		int i=0;
		if (index > 999) {
			str = str+"_"+ index;
		} else if (index > 99) {
			str = str+"_" + new String(new char[num-3]).replace('\0', '0') + index;
		} else if (index > 9 ){
			str = str+"_" + new String(new char[num-2]).replace('\0', '0') + index;
		} else {
			str = str+"_" + new String(new char[num-1]).replace('\0', '0') + index;
		}
		
		return str;
	}

	public static void main(String[] args) {

		Log4jInit.logger.info("aa" + "\\" + "bb");
		StringBuilder jsonStringBuilder = new StringBuilder();
		try {
			BufferedReader br = new BufferedReader(
					new FileReader(new File("D:\\Documents\\lab_file\\rubic\\json\\55555.json")));
			// BufferedReader br = new BufferedReader(new FileReader(new
			// File("C:/Users/Administrator/Desktop/json/new_model_parse.json")));
			String temp = "";
			while ((temp = br.readLine()) != null) {
				jsonStringBuilder.append(temp);
			}
			br.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		JSONObject json = JSONObject.parseObject(jsonStringBuilder.toString());
		JSONObject taskJson = json;// JSONObject.fromObject(json);
		ParseTaskJson t = new ParseTaskJson();
		JSONArray blocksArray = taskJson.getJSONArray("blocks");
		JSONArray blockIds = new JSONArray();
		JSONObject paramJsonObject = new JSONObject();
		for (int i = 0; i < blocksArray.size(); i++) {
			JSONObject oneBlock = blocksArray.getJSONObject(i);

			if (!(oneBlock.getString("blockId").contains("uiData") || oneBlock.getString("blockId").contains("uiStart")
					|| oneBlock.getString("blockId").contains("uiEnd"))) {
				paramJsonObject.put(oneBlock.getString("blockId"), oneBlock.getJSONArray("paramsConfig"));
				blockIds.add(oneBlock.getString("blockId"));
			}
		}
		JSONArray inputJsonArray = taskJson.getJSONArray("inputs");
		JSONArray outputJsonArray = taskJson.getJSONArray("outputs");
		JSONArray dataJsonArray = taskJson.getJSONArray("data");
		JSONArray settingsArray = new JSONArray();
		for (int m = 0; m < inputJsonArray.size(); m++) {
			JSONObject oneFinal = new JSONObject();
			JSONArray oneTaskInputArray = inputJsonArray.getJSONArray(m);
			JSONObject algorithmInput = new JSONObject();
			for (int k = 0; k < oneTaskInputArray.size(); k++) {
				JSONObject oneAlgorithmInput = oneTaskInputArray.getJSONObject(k);
				if (algorithmInput.containsKey(oneAlgorithmInput.getString("blockId"))) {
					algorithmInput.getJSONArray(oneAlgorithmInput.getString("blockId")).add(oneAlgorithmInput);
				} else {
					JSONArray temp = new JSONArray();
					temp.add(oneAlgorithmInput);
					algorithmInput.put(oneAlgorithmInput.getString("blockId"), temp);
				}
			}
			oneFinal.put("inputs", algorithmInput);

			JSONObject oneTaskOutputObject = new JSONObject();
			oneTaskOutputObject.put("outputs", outputJsonArray.getJSONArray(m));
			oneFinal.put("outputs", oneTaskOutputObject);
			JSONObject algorithmParam = new JSONObject();
			for (int h = 0; h < blockIds.size(); h++) {
				String blockId = blockIds.getString(h);
				algorithmParam.put(blockId, paramJsonObject.getJSONArray(blockId).getJSONArray(m));
			}
			oneFinal.put("params", algorithmParam);
			oneFinal.put("data", dataJsonArray.getJSONArray(m));
			settingsArray.add(oneFinal);
		}
		for (int index = 0; index < settingsArray.size(); index++) {
			String subTaskHash = UUID.randomUUID().toString().substring(0, 20);
			RunningTaskBean runningTaskBean = new RunningTaskBean("task.getTask_id()" + "", subTaskHash,
					jsonStringBuilder.toString(), "task.getName()");
			runningTaskBean.setBatchTaskHash("batchTaskHash");
			TaskThread taskA = new TaskThread(runningTaskBean);

			taskA.runningTaskBean.runnableObjects = t.toRunnerableObjectMap(taskA, index + 1,
					settingsArray.getJSONObject(index).getJSONArray("data"),
					settingsArray.getJSONObject(index).getJSONObject("inputs"),
					settingsArray.getJSONObject(index).getJSONObject("outputs"),
					settingsArray.getJSONObject(index).getJSONObject("params"));
		}
		// Log4jInit.logger.info(JSONObject.fromObject(jsonStringBuilder.toString()).toString());
		// ParseTaskJson parser = new ParseTaskJson();
		// RunningTaskBean runningTaskBean = new
		// RunningTaskBean("taskId","taskHash",jsonStringBuilder.toString(),"taskName");
		// TaskThread task = new TaskThread(runningTaskBean);
		// JSONObject json =
		// JSONObject.fromObject(jsonStringBuilder.toString());
		// JSONObject settingArray =
		// json.getJSONArray("settings").getJSONObject(0);
		// JSONObject inputJson = settingArray.getJSONObject("inputs");
		// JSONObject outputJson = settingArray.getJSONObject("outputs");
		// JSONObject paramJson = settingArray.getJSONObject("params");
		// JSONArray dataJson = settingArray.getJSONArray("data");
		// parser.toRunnerableObjectMap(task,0, dataJson,
		// inputJson,outputJson,paramJson);
		// RunningTaskBean runningTaskBean2 = new
		// RunningTaskBean("taskId","taskHash",jsonStringBuilder.toString(),"taskName");
		// TaskThread task2 = new TaskThread(runningTaskBean2);
		// JSONObject inputJson2 = json.getJSONArray("inputs").getJSONObject(1);
		// JSONArray outputJson2 = json.getJSONArray("outputs").getJSONArray(1);
		// JSONObject paramJson2 = json.getJSONArray("params").getJSONObject(1);
		// JSONArray dataJson2 = json.getJSONArray("data").getJSONArray(1);
		// JSONObject outputFinal2 = new JSONObject();
		// outputFinal2.put("suffix",".txt");
		// parser.toRunnerableObjectMap(task2,1, dataJson2,
		// inputJson2,outputFinal2,paramJson2);
	}

	public void setJSON(JSONObject jb) {
		this.taskJson = jb;
		this.otherConfig = taskJson.getJSONArray("other").getJSONObject(0);
		this.blockParseResult = this.parseTaskJson(this.taskJson);
	}

	public void setJSON(String json) {
		// Time2Str.printCurrentTime("taskJSON lenght = "+json.length());
		this.taskJson = JSONObject.parseObject(json);
		// Time2Str.printCurrentTime("taskJSON lenght = "+json.length());
		this.otherConfig = taskJson.getJSONArray("other").getJSONObject(0);
		this.blockParseResult = this.parseTaskJson(this.taskJson);
	}

	/**
	 * parse json to runnable algorithm or sub-task
	 * 
	 * @param task
	 * @return
	 */
	public Map<String, Object> toRunnerableObjectMap(TaskThread task, int taskIndex, JSONArray dataJson,
			JSONObject inputJson, JSONObject outputJson, JSONObject paramJson) {
		// long startTime = System.currentTimeMillis();
		// String tbJson=task.runningTaskBean.getJson();
		// Map<String, UIBlock> blockParseResult =
		// this.parseTaskJson(this.taskJson);

		/**
		 * parse start blocks
		 */

		for (Map.Entry<String, Integer> startObject : blockParseResult.get("uiStart_1").postBlockMap.entrySet()) {
			blockParseResult.get(startObject.getKey()).inputConfig = parseInputs(
					inputJson.getJSONArray(startObject.getKey()), blockParseResult.get(startObject.getKey()), null);
		}
		HashMap<String, String> inputsMap = this.produceInputMap(blockParseResult, task, dataJson);
		HashMap<String, String> outputsMap = this.produceOutputMap(task.runningTaskBean.getTaskName(), taskIndex,
				outputJson, blockParseResult);
		String parallelStrategy = otherConfig.getString("ParallelStrategy");
		String priority = otherConfig.getString("Priority");
		String hostGroup = otherConfig.getString("HostGroup");
		Map<String, Object> runnableObjects = new HashMap<>();
		String runnableAlgorithmsHash = "";
		String runnableModelsHash = "";

		for (Map.Entry<String, UIBlock> oneBlock : blockParseResult.entrySet()) {
			// 不是start、data、end中的任何一个
			if (!(oneBlock.getKey().contains("uiStart") || oneBlock.getKey().contains("uiData")
					|| oneBlock.getKey().contains("uiEnd"))) {
				beans.RunnableAlgorithm runnableAlgorithm = new beans.RunnableAlgorithm();
				runnableAlgorithm.postBlockMap = oneBlock.getValue().postBlockMap;
				runnableAlgorithm.preBlockMap = oneBlock.getValue().preBlockMap;
				runnableAlgorithm.setBlockId(oneBlock.getKey());
				runnableAlgorithm.setAlgorithmDetail((AlgorithmDetail) oneBlock.getValue().getAlgorithmOrModel());
				runnableAlgorithm.inputValues = this.parseBlockInputs(inputsMap, oneBlock.getValue(),
						runnableAlgorithm.getAlgorithmDetail().getPlatform());
				/*
				 * runnableAlgorithm.outputValues =
				 * this.generateAlgorithmOutputs(outputsMap,runnableAlgorithm.
				 * getAlgorithmDetail().getPlatform(),
				 * runnableAlgorithm,task.runningTaskBean.getTaskHash());
				 */
				runnableAlgorithm.outputValues = this.generateAlgorithmOutputs(outputsMap,
						runnableAlgorithm.getAlgorithmDetail().getPlatform(), runnableAlgorithm,
						task.runningTaskBean.getTaskName(), taskIndex);
				runnableAlgorithm.setParallelStrategy(parallelStrategy);
				runnableAlgorithm.setPriority(priority);
				runnableAlgorithm.setHostGroup(hostGroup);
				/**
				 * produce UIParamConfig list
				 */
				oneBlock.getValue().paramConfig = parseParams(paramJson.getJSONArray(oneBlock.getKey()));
				runnableAlgorithm.setParamValues(blockParseResult.get(oneBlock.getKey()).getParamMap());
				/**
				 * the start block is identified by connected with start block
				 * which has the block id : uiStart_1 put start block hash into
				 * a string , split in ","
				 *
				 */
				if (oneBlock.getValue().preBlockMap.containsKey("uiStart_1")) {
					if (oneBlock.getValue().isAlgorithm()) {
						runnableAlgorithmsHash += oneBlock.getKey() + ",";
					} else {
						runnableModelsHash += oneBlock.getKey() + ",";
					}
				}
				runnableObjects.put(runnableAlgorithm.getBlockId(), runnableAlgorithm);
				UIAlgorithmDetail uiAlgorithmDetail = new UIAlgorithmDetail();
				uiAlgorithmDetail.setAlgorithmId(blockParseResult.get(oneBlock.getKey()).getId());
				uiAlgorithmDetail.setBlockId(oneBlock.getKey());
			}
		}
		/**
		 * print result
		 */
		if (runnableAlgorithmsHash != "") {
			runnableObjects.put("startAlgorithms",
					runnableAlgorithmsHash.substring(0, runnableAlgorithmsHash.lastIndexOf(",")));
		}
		// Log4jInit.logger.info("88787");
		if (runnableModelsHash != "") {
			runnableObjects.put("startModels", runnableModelsHash.substring(0, runnableModelsHash.lastIndexOf(",")));
		}
		// for (Map.Entry<String, Object> oneObject :
		// runnableObjects.entrySet()) {
		// Log4jInit.logger.info("keyyyyy:"+oneObject.getKey()+": " +
		// oneObject.getValue().toString());
		// }
		// Log4jInit.logger.info("time:"+(System.currentTimeMillis()-startTime)/1000+"s");
		return runnableObjects;
	}

	public ArrayList<UIAlgorithmDetail> getOrderedDetails() {
		ArrayList<String> temp = new ArrayList<>();
		for (Iterator<UIAlgorithmDetail> it = orderedDetails.iterator(); it.hasNext();) {
			UIAlgorithmDetail uiAlgorithmDetail = it.next();
			if (temp.contains(uiAlgorithmDetail.getBlockId())) {
				it.remove();
			}
			uiAlgorithmDetail.setAlgorithmId(blockParseResult.get(uiAlgorithmDetail.getBlockId()).getId());
			temp.add(uiAlgorithmDetail.getBlockId());
		}
		ArrayList<UIAlgorithmDetail> result = orderedDetails;
		orderedDetails = new ArrayList<>();
		return result;
	}
	// private void pickAlgorithm(String blockId){
	// if(blockId==null){
	// blockId = "uiStart_1";
	// }
	// UIBlock startBlock = tempBlocks.get(blockId);
	// ArrayList<String> orderedNames = new ArrayList<>();
	// for(Map.Entry<String,Integer> one:startBlock.postBlockMap.entrySet()){
	// UIAlgorithmDetail uiAlgorithmDetail = new UIAlgorithmDetail();
	// uiAlgorithmDetail.setBlockId(one.getKey());
	// if(!one.getKey().contains("uiEnd"))
	// orderedNames.add(one.getKey());
	// uiAlgorithmDetail.setAlgorithmId(tempBlocks.get(one.getKey()).getId());
	// orderedDetails.add(uiAlgorithmDetail);
	// }
	// if(orderedNames.size()!=0){
	// for(String name:orderedNames){
	// pickAlgorithm(name);
	// }
	// }
	// }

	private String getOutputSuffix(String algorithmId, String outputName) {
		String result = "";
		for (AlgorithmOutput algorithmOutput : algorithmDetails.get(algorithmId).getAlgorithmOutputs()) {
			if (algorithmOutput.getOutputName().equals(outputName)) {
				result = algorithmOutput.getSuffix();
			}
		}
		return result;
	}

	public Set<String> parseAlgorithmIds(String taskJson) {
		JSONObject taskJsonObject = JSONObject.parseObject(taskJson);
		return parseAlgorithmIds(taskJsonObject);
	}

	public Set<String> parseAlgorithmIds(JSONObject taskJson) {
		Set<String> result = new HashSet<>();
		JSONArray blocks = taskJson.getJSONArray("blocks");
		for (int i = 0; i < blocks.size(); i++) {
			JSONObject oneBlock = blocks.getJSONObject(i);
			if (oneBlock.containsKey("dataId") && oneBlock.getString("blockId").contains("uiAlgorithm"))
				result.add(oneBlock.getString("dataId"));
		}
		return result;
	}

	/**
	 * parse json to runnable algorithm or sub-task
	 * 
	 * @param task
	 * @param priority
	 *            优先级
	 * @param parallelStrategy
	 *            调度策略 可能参数：按CPU可利用率最大（ut） 按CPU可利用率最小（-ut） 按内存剩余最大（mem）
	 *            按内存剩余最小（-mem）
	 * @return
	 */
	// @SuppressWarnings("Duplicates")
	public void setModleJSON(JSONObject json) {
		this.taskJson = json;
		Log4jInit.logger.info(json.toString());
		this.blockParseResult = this.parseModelJsonToBlock(taskJson);

	}

	public Map<String, Object> toRunnerableObjectMapModel(TaskThread task, String priority, String parallelStrategy) {

		/**
		 * parse start blocks
		 */
		Map<String, Object> runnableObjects = new HashMap<>();
		String runnableAlgorithmsHash = "";

		for (Map.Entry<String, UIBlock> oneBlock : blockParseResult.entrySet()) {
			// 不是start、data、end中的任何一个
			if (!(oneBlock.getKey().contains("uiStart") || oneBlock.getKey().contains("uiData")
					|| oneBlock.getKey().contains("uiEnd"))) {
				beans.RunnableAlgorithm runnableAlgorithm = new beans.RunnableAlgorithm();
				runnableAlgorithm.postBlockMap = oneBlock.getValue().postBlockMap;
				runnableAlgorithm.preBlockMap = oneBlock.getValue().preBlockMap;
				runnableAlgorithm.setBlockId(oneBlock.getKey());
				runnableAlgorithm.setAlgorithmDetail((AlgorithmDetail) oneBlock.getValue().getAlgorithmOrModel());
				runnableAlgorithm.setParallelStrategy(parallelStrategy);
				runnableAlgorithm.setPriority(priority);

				runnableObjects.put(runnableAlgorithm.getBlockId(), runnableAlgorithm);
				UIAlgorithmDetail uiAlgorithmDetail = new UIAlgorithmDetail();
				uiAlgorithmDetail.setAlgorithmId(blockParseResult.get(oneBlock.getKey()).getId());
				uiAlgorithmDetail.setBlockId(oneBlock.getKey());
			}
			/**
			 * the start block is identified by connected with start block which
			 * has the block id : uiStart_1 put start block hash into a string ,
			 * split in ","
			 *
			 */
			if (oneBlock.getKey().contains("uiStart_1")) {
				for (Map.Entry<String, Integer> entry : oneBlock.getValue().postBlockMap.entrySet()) {
					runnableAlgorithmsHash += entry.getKey() + ",";

				}
			}
		}

		/**
		 * print result
		 */
		if (runnableAlgorithmsHash != "") {
			runnableObjects.put("startAlgorithms",
					runnableAlgorithmsHash.substring(0, runnableAlgorithmsHash.lastIndexOf(",")));
		}
		// Log4jInit.logger.info("88787");

		for (Map.Entry<String, Object> oneObject : runnableObjects.entrySet()) {
			Log4jInit.logger.info("keyyyyy:" + oneObject.getKey() + ":  " + oneObject.getValue().toString());
		}
		// Log4jInit.logger.info("time:"+(System.currentTimeMillis()-startTime)/1000+"s");
		return runnableObjects;
	}

	/**
	 * parse the pre and post relationship between blocks
	 * 
	 * @param json
	 * @return map(key : block id ; value : UIBlock)
	 */
	// @SuppressWarnings("Duplicates")
	public Map<String, UIBlock> parseModelJsonToBlock(JSONObject jsonObject) {
		if (this.blockParseResult.size() == 0) {
			// JSONObject jsonObject = JSONObject.fromObject(json);
			List<String> firstBlock = new ArrayList<>();
			JSONArray blocksArray = jsonObject.getJSONArray("blocks");
			/**
			 * record a block is algorithm or model key:block id value: 1:is
			 * algorithm 0:is model
			 */
			Map<String, Integer> algorithmOrModel = new HashMap<>();
			for (int a = 0; a < blocksArray.size(); a++) {
				JSONObject block = blocksArray.getJSONObject(a);
				String blockId = block.getString("blockId");
				if (!(blockId.contains("uiStart") || blockId.contains("uiEnd") || blockId.contains("uiData"))) {
					algorithmOrModel.put(blockId, block.getString("isAlgorithm").equals("1") ? 1 : 0);
				} else {
					algorithmOrModel.put(blockId, 2);
				}
			}
			Log4jInit.logger.info("parseModelJsonToBlock");
			/**
			 * produce block map key:blockId value:block json
			 */
			Map<String, JSONObject> blocksMap = new HashMap<>();
			for (int i = 0; i < blocksArray.size(); i++) {
				JSONObject blockObject = JSONObject.parseObject(blocksArray.get(i).toString());
				blocksMap.put(blockObject.getString("blockId"), blockObject);
			}

			Log4jInit.logger.info("parseModelJsonToBlock");
			/**
			 * produce line list
			 */
			// JSONArray lines = jsonObject.getJSONArray("lines");
			Collection<?> uiLines = JSONArray.parseArray(jsonObject.getString("lines"), UILine.class);// (lines,
																										// UILine.class);
			ArrayList<UILine> lineList = new ArrayList<>();
			for (Object o : uiLines) {
				lineList.add((UILine) o);
			}

			Log4jInit.logger.info("parseModelJsonToBlock");
			/**
			 * parse each block, produce each one's postMap
			 */
			Map<String, UIBlock> blocks = new HashMap<>();
			blocks.put("uiEnd", new UIBlock());
			for (UILine line : lineList) {
				if (!line.getPageTargetId().contains("uiEnd")) {
					orderedDetails.add(new UIAlgorithmDetail(line.getPageTargetId()));
				} else {
					blocks.get("uiEnd").preBlockMap.put(line.getPageSourceId(),
							algorithmOrModel.get(line.getPageSourceId()));
				}
				if (line.getPageSourceId().equals("uiStart_1")) {
					firstBlock.add(line.getPageTargetId());
				}
				if (!blocks.containsKey(line.getPageSourceId())) {
					UIBlock sourceBlock = new UIBlock();
					sourceBlock.setBlockId(line.getPageSourceId());
					sourceBlock.postBlockMap.put(line.getPageTargetId(), algorithmOrModel.get(line.getPageTargetId()));
					blocks.put(line.getPageSourceId(), sourceBlock);
				} else {
					blocks.get(line.getPageSourceId()).postBlockMap.put(line.getPageTargetId(),
							algorithmOrModel.get(line.getPageTargetId()));
				}
			}

			Log4jInit.logger.info("parseModelJsonToBlock");
			for (Map.Entry<String, JSONObject> block : blocksMap.entrySet()) {
				if (!(block.getKey().contains("uiStart") || block.getKey().contains("uiEnd")
						|| block.getKey().contains("uiData"))) {
					/**
					 * parse current block into UIBlock bean
					 */
					UIBlock tempBlock = blocks.get(block.getKey());
					tempBlock.setId(block.getValue().getString("dataId"));
					tempBlock.setAlgorithm(block.getValue().getString("isAlgorithm").equals("1"));
					if (tempBlock.isAlgorithm()) {
						AlgorithmDetail algorithmDetail = algorithmDao
								.getAlgorithmDetailWithoutUserId(tempBlock.getId());
						if (block.getValue().containsKey("cpuNum")) {
							algorithmDetail.setCpuNum(block.getValue().getString("cpuNum"));
						}
						algorithmDetails.put(tempBlock.getId(), algorithmDetail);
						tempBlock.setAlgorithmOrModel(algorithmDetails.get(tempBlock.getId()));
					}

				}

			}
			Log4jInit.logger.info("parseModelJsonToBlock");
			this.blockParseResult = blocks;
		}
		return this.blockParseResult;

	}
}
